/************************************************************************
  * Copyright(c) 2023 Levetop Semiconductor Co.,Led. All rights reserved.
  * @file     function_drv.c
  * @author   UartTFT Application Team
  * @version  V0.0.1
  * @date     2023-01-01
  * @brief    
 *************************************************************************/

#include "function_drv.h"
#include "delay.h"
#include "pwm_drv.h"
#include "eport_drv.h"
#include "spi_drv.h"
#include "dmac_drv.h"
#include "cpm_drv.h"
#include "ioctrl_drv.h"
#include "uart_drv.h"
#include "ccm_drv.h"
#include "transport.h"
#include "dma.h"

/*------------------------------------Backlight---------------------------------------------*/
void LCD_BL_Init(uint16_t duty)
{
	// prescale: PWM_Prescaler+1
	// PWM_Csr: 0=1/2, 1=1/4, 2=1/8, 3=1/16, others=1
	// period: WM_Period+1
	// Actual PWM output: 75Mhz/(PWM_Prescaler+1)/(PWM_Csr)/(PWM_Period+1)
	/*PWM[3]/GINT[15]*/
	PWM_ConfigGpio(PWM_PORT3, GPIO_OUTPUT, ENABLE);
	PWM_WriteGpioData(PWM_PORT3, Bit_SET);
	PWM_OutputInit(PWM_PORT3, 4, PWM_CLK_DIV_1, 499, duty, 0); // 74=2k  24=6k   14=10k   4=30k
}

// close backlight
void LT_BacklightClose(void)
{
	PWM->PWM_CR_CH3 &= ~CH3EN;
	PWM_WriteGpioData(PWM_PORT3, Bit_RESET);
}

// open backlight
void LT_BacklightOpen(void)
{
	PWM->PWM_CR_CH3 |= CH3EN;
	PWM_WriteGpioData(PWM_PORT3, Bit_SET);
}

// set backlight
void LT_BacklightSet(uint16_t duty)
{
	if (duty == gDutyBuf[0])
		LT_BacklightClose();
	else
	{
		PWM->PWM_CMR3 = duty; // high leve = duty+1
		LT_BacklightOpen();
	}
}

/*------------------------------------Buzzer---------------------------------------------*/
void touch_buzzer_init(void)
{
#if LT_TOUCH_BUZZER
	PWM_OutputInit(PWM_PORT2, 2, PWM_CLK_DIV_1, 30000, 15000, 0);
	DelayMS(20);
	PWM_Stop(PWM_PORT2);
#endif
}

void touch_buzzer(void)
{
#if LT_TOUCH_BUZZER
	buzzer_start = 1;
	// PWM_WriteGpioData(PWM_PORT2,Bit_RESET);
	PWM_Start(PWM_PORT2);
#endif
}

void touch_buzzer_close(void)
{
#if LT_TOUCH_BUZZER
	// PWM_WriteGpioData(PWM_PORT2,Bit_SET);
	PWM_Stop(PWM_PORT2);
#endif
}

/*------------------------------------Wav---------------------------------------------*/
void WAV_amplifier_EN(void)
{
	//EPORT_ConfigGpio(EPORT_PIN32, GPIO_OUTPUT);	
	//EPORT_WriteGpioData(EPORT_PIN32, Bit_SET);	
}

void WAV_amplifier_DIS(void)
{
	//EPORT_ConfigGpio(EPORT_PIN32, GPIO_OUTPUT);
	//EPORT_WriteGpioData(EPORT_PIN32, Bit_RESET);
}

/*------------------------------------Encoder---------------------------------------------*/
void Encoder_Init(void)
{
	// IO_Ctrl_SCI_Swap(TX1_GINT4,TRUE);
	// IO_Ctrl_SCI_Swap(RX1_GINT0,TRUE);
	UART_ConfigGpio(SCI1, UART_TX, GPIO_INPUT); // A
	UART_ConfigGpio(SCI1, UART_RX, GPIO_INPUT); // B
	UART_WriteGpioData(SCI1, UART_TX, Bit_SET);
	UART_WriteGpioData(SCI1, UART_RX, Bit_SET);

	IOCTRL->SWAP_CONTROL_REG |= (1 << 0); // KEY
	EPORT_WriteGpioData(EPORT_PIN10, 1);
	EPORT_ConfigGpio(EPORT_PIN10, GPIO_INPUT);
	EPORT_Init(EPORT_PIN10, FALLING_EDGE_INT); // RISING_EDGE_INT
}

/*------------------------------------SD card---------------------------------------------*/
void SD_SPIx_Initial(void)
{
	// disable spi/Eport interrupt
	// EPORT1->EPIER &=~ (0x01<<1);   //gint[9:11]
	// EPORT1->EPIER &=~ (0x01<<2);   //gint[9:11]
	// EPORT1->EPIER &=~ (0x01<<3);   //gint[9:11]

	IOCTRL->SWAP_CONTROL_REG &= ~(1 << 0); // enable spi function(sck3,miso3,mosi3 /gint[9:11])
	IOCTRL->SPI_CONTROL_REG |= 0x03;	   // enhance SPI driving capability
	//	IOCTRL->SPI_CONTROL_REG &=~(1<<2);		//set SPI voltage conversion rate to high speed

	SPI_ConfigGpio(SDSPI, SPI_SS, GPIO_OUTPUT); // cs

	SPI_InitTypeDef SPI_InitStruct;
	SPI_Cmd(SDSPI, DISABLE);
	// SPI module configuration
	SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
	SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
	SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
	SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
	SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
	SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
	SPI_InitStruct.SPI_CRCPolynomial = 7;
	SPI_Init(SDSPI, &SPI_InitStruct);

	SDSPI->SPIDMACR &= (~0x03); // disable SPI DMA

	SPI_Cmd(SDSPI, ENABLE);
	SD_SPIx_ReadWriteByte(0xff);
}

uint16_t SD_SPIx_ReadWriteByte(uint16_t TxData)
{
	uint16_t retry = 0;
	while ((SDSPI->SPISRHW) & (SPISR_TXFFULL_MASK)) // The waiting sending area is empty
	{
		retry++;
		if (retry >= 0XFFFE)
			return 0; // Timeout exit
	}
	SDSPI->SPIDR = TxData; // Send a byte
	retry = 0;
	while ((SDSPI->SPISRHW) & (SPISR_RXFEMP_MASK)) // Wait for receiving a byte
	{
		retry++;
		if (retry >= 0XFFFE)
			return 0; // Timeout exit
	}
	return SDSPI->SPIDR; // Return received data
}

void SD_SPIx_SetSpeed(uint16_t speed)
{
	SPI_Cmd(SDSPI, DISABLE);

	SPI_InitTypeDef SPI_InitStruct;

	/* SPI1 Config */
	SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
	SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
	SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
	SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
	SPI_InitStruct.SPI_BaudRatePrescaler = speed;
	SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
	SPI_InitStruct.SPI_CRCPolynomial = 7;

	SPI_Init(SDSPI, &SPI_InitStruct);
	SPI_Cmd(SDSPI, ENABLE);

	SD_SPIx_ReadWriteByte(0xff);
}

void SD_SPIx_DMA_Tran(uint8_t *Tx_Addr, uint8_t *Rx_Addr, uint32_t length)
{
	// DMA_Init(DMA2_BASE_ADDR);
	SDSPI->SPIDMACR |= 0x03; // enable SPI TX RX DMA
	SDSPI_dma_control->DMA_CONFIG = 1;

	// tx
	SDSPI_dma_channel[0]->DMA_SADDR = (uint32_t)Tx_Addr;
	SDSPI_dma_channel[0]->DMA_DADDR = (uint32_t)&SDSPI->SPIDR;
	SDSPI_dma_channel[0]->DMA_CTRL_HIGH = length;
	SDSPI_dma_channel[0]->DMA_CTRL = DNOCHG | SIEC | M2P_DMA;
	SDSPI_dma_channel[0]->DMA_CFG = (HS_SEL_SRC_SOFT);
	SDSPI_dma_channel[0]->DMA_CFG_HIGH = SDSPI_DST_TX;

	// rx
	SDSPI_dma_channel[1]->DMA_SADDR = (uint32_t)&SDSPI->SPIDR;
	SDSPI_dma_channel[1]->DMA_DADDR = (uint32_t)Rx_Addr;
	SDSPI_dma_channel[1]->DMA_CTRL_HIGH = length;
	SDSPI_dma_channel[1]->DMA_CTRL = SNOCHG | DIEC | P2M_DMA;
	SDSPI_dma_channel[1]->DMA_CFG = (HS_SEL_DST_SOFT);
	SDSPI_dma_channel[1]->DMA_CFG_HIGH = SDSPI_SRC_RX;

	// m_dma2_control->DMA_CONFIG = 0;
	SDSPI_dma_control->DMA_MASKTFR = CHANNEL_UMASK(0) | CHANNEL_UMASK(1);
	SDSPI_dma_control->DMA_CHEN = CHANNEL_WRITE_ENABLE(0) | CHANNEL_ENABLE(0) | CHANNEL_WRITE_ENABLE(1) | CHANNEL_ENABLE(1);
}

void SD_SPIx_DMA_Wait(void)
{
	while ((SDSPI_dma_control->DMA_RAWTFR & (CHANNEL_STAT(0) | CHANNEL_STAT(1))) != (CHANNEL_STAT(0) | CHANNEL_STAT(1)))
		;

	SDSPI_dma_control->DMA_CLRTFR = (CHANNEL_STAT(0) | CHANNEL_STAT(1));

	SDSPI_dma_control->DMA_CHEN = 0;
	// m_dma2_control->DMA_CONFIG = 0;
	SDSPI->SPIDMACR &= (~0x03); // diable SPI TX RX DMA
}

void SD_IN_Enable(void) // Enable WakeUp
{
	CPM->CPM_PADWKINTCR |= (1 << 17);
}

uint8_t SD_detection(void) // return WakeUp pin level
{
	if (CPM->CPM_PADWKINTCR & 0x02000000)
		return 1;
	return 0;
}
void SD_SPI_close(void)
{
//	SPI_ConfigGpio(SPI3, SPI_SS, GPIO_OUTPUT);	 // SD_SS
//	SPI_ConfigGpio(SPI3, SPI_SCK, GPIO_OUTPUT);	 // SD_CLK --- LCD_WR
//	SPI_ConfigGpio(SPI3, SPI_MOSI, GPIO_OUTPUT); // SD_MOSI --- LCD_RD
//	SPI_ConfigGpio(SPI3, SPI_MISO, GPIO_OUTPUT); // SD_MISO
}


#if 0
    /*only for test*/
	//--pin43  pin44,default Pull up
	IO_Ctrl_SCI_Swap(TX1_GINT4,TRUE); //OPEN TX1 RX1 
	IO_Ctrl_SCI_Swap(RX1_GINT0,TRUE);	
	UART_ConfigGpio(SCI1, UART_TX, GPIO_OUTPUT);
	UART_WriteGpioData(SCI1, UART_TX, Bit_SET);

	while(1)
	{
		//SCI3->SCICR2 &=~(1<<2)|(1<<3)|(1<<5);
		IO_Ctrl_SCI_Swap(TX3_GINT1,TRUE); //OPEN TX1 RX1 
		//IO_Ctrl_SCI_Swap(RX3_GINT2,TRUE);
		UART_ConfigGpio(SCI3, UART_TX, GPIO_OUTPUT);   
		UART_ConfigGpio(SCI3, UART_RX, GPIO_OUTPUT);    	   
		UART_WriteGpioData(SCI3, UART_TX, Bit_SET);          	
		UART_WriteGpioData(SCI3, UART_RX, Bit_SET);          	
		DelayMS(1000);

		UART_WriteGpioData(SCI3, UART_TX, Bit_RESET);          		
		UART_WriteGpioData(SCI3, UART_RX, Bit_RESET);          		
		DelayMS(1000);
	}
#endif
